﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CommonBehaviors.Actions;
using Styx;
using Styx.CommonBot;
using Styx.Patchables;
using Styx.Pathing;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Styx.TreeSharp;
#if USE_DUNGEONBUDDY_DLL
using Bots.DungeonBuddyDll;
using Bots.DungeonBuddyDll.Profiles;
using Bots.DungeonBuddyDll.Attributes;
using Bots.DungeonBuddyDll.Helpers;
using Action = Styx.TreeSharp.Action;

namespace Bots.DungeonBuddyDll.Dungeon_Scripts.Classic
#else
    using Bots.DungeonBuddy.Profiles;
    using Bots.DungeonBuddy.Attributes;
    using Bots.DungeonBuddy.Helpers;
    using Action = Styx.TreeSharp.Action;
namespace Bots.DungeonBuddy.Dungeon_Scripts.Classic
#endif
{
    public class ScarletHalls : Dungeon
    {
        #region Overrides of Dungeon

        public override uint DungeonId { get { return 163; } }

        public override WoWPoint Entrance
        {
            get
            {
                return new WoWPoint(2864.618, -823.2136, 160.3323);
                ;
            }
        }

        public override WoWPoint ExitLocation { get { return new WoWPoint(820.4927, 614.8466, 13.50341); } }

        public override void RemoveTargetsFilter(List<WoWObject> units)
        {
            units.RemoveAll(
                ret =>
                {
                    var unit = ret as WoWUnit;
                    if (unit != null)
                    {
                        if (unit.Entry == ObedientHound && unit.Location.DistanceSqr(_houndMasterRoomCenter) > 15 * 15)
                            return true;
                        // ignore Commander Lindon or the master archers if they don't have a target and I don't have an archery target on.
                        if ((unit.Entry == CommanderLindonId || unit.Entry == MasterArcher) && StyxWoW.Me.IsTank() && !StyxWoW.Me.HasAura("Heroic Defense") && !unit.GotTarget)
                            return true;
                    }
                    return false;
                });
        }

        public override void IncludeTargetsFilter(List<WoWObject> incomingunits, HashSet<WoWObject> outgoingunits)
        {
            foreach (var obj in incomingunits)
            {
                var unit = obj as WoWUnit;
                if (unit != null)
                {
                    // in some CCs the healer won't heal unless there are units in the target list.
                    if (unit.Entry == CommanderLindonId && StyxWoW.Me.IsHealer())
                        outgoingunits.Add(unit);

                    if (unit.Entry == ScarletCannoneer)
                    {
                        var tank = ScriptHelpers.Tank;
                        if (tank != null && tank.GotTarget && tank.CurrentTargetGuid == unit.Guid)
                            outgoingunits.Add(unit);
                    }
                }
            }
        }

        public override void WeighTargetsFilter(List<Targeting.TargetPriority> units)
        {
            foreach (var priority in units)
            {
                var unit = priority.Object as WoWUnit;
                if (unit != null)
                {
                    if (unit.Entry == ObedientHound && unit.Location.DistanceSqr(_houndMasterRoomCenter) <= 15 * 15)
                        priority.Score += 400;

                    if (unit.Entry == ScarletScholar && StyxWoW.Me.IsDps())
                        priority.Score += 400;
                }
            }
        }

        #endregion

        private const int LootSparklesAuraId = 113628;

        private const uint CommanderLindonId = 59191;
        private const uint MasterArcher = 59175;
        private const uint ObedientHound = 59309;
        private const uint ArmsmasterHarlan = 58632;
        private const uint ScarletScholar = 59372;
        private const uint ScarletCannoneer = 59293;

        private readonly WoWPoint _houndMasterRoomCenter = new WoWPoint(1009.557, 513.6875, 12.9061);

        private WoWUnit ReinforcedArcheryTarget { get { return ObjectManager.GetObjectsOfType<WoWUnit>().Where(u => u.Entry == 59163 && u.DistanceSqr <= 25 * 25 && u.HasAura(LootSparklesAuraId)).OrderBy(u => u.DistanceSqr).FirstOrDefault(); } }

        public Composite Root() { return new PrioritySelector(); }

        [EncounterHandler(59191, "Commander Lindon", BossRange = 100, Mode = CallBehaviorMode.Proximity)]
        public Composite CommanderLindonEncounter()
        {
            const uint ExplodingShotStalker = 59683;

            WoWUnit shield = null;

            return new PrioritySelector(
                ScriptHelpers.CreateRunAwayFromBad(ctx => !StyxWoW.Me.HasAura("Heroic Defense") && StyxWoW.Me.IsTank() || !StyxWoW.Me.IsTank(), 7, ExplodingShotStalker),
                new Decorator(ctx => StyxWoW.Me.HasAura("Heroic Defense"), new Helpers.Action<WoWUnit>(boss => Navigator.MoveTo(boss.Location))),
                // pickup a shield 
                new Decorator(
                    ctx =>
                    !StyxWoW.Me.HasAura("Heroic Defense") && !StyxWoW.Me.IsHealer() && Targeting.Instance.IsEmpty() && (StyxWoW.Me.IsTank() || ScriptHelpers.Tank.HasAura("Heroic Defense")) &&
                        // cache the ReinforcedArcheryTarget 
                    (shield = ReinforcedArcheryTarget) != null,
                    new PrioritySelector(
                        new Decorator(ctx => shield.WithinInteractRange, new Action(ctx => shield.Interact())),
                        new Decorator(ctx => !shield.WithinInteractRange, new Action(ctx => Navigator.MoveTo(shield.Location))))));
        }

        [EncounterHandler(59303, "Houndmaster Braun")]
        public Composite HoundmasterBraunBehavior()
        {
            return
                new PrioritySelector(
                    new Decorator(
                        ctx => StyxWoW.Me.IsTank() && ObjectManager.GetObjectsOfType<WoWUnit>().Any(u => u.Entry == ObedientHound && u.CurrentTargetGuid == StyxWoW.Me.Guid),
                        new Action(ctx => Navigator.MoveTo(_houndMasterRoomCenter))),

                    new Decorator(ctx => StyxWoW.Me.Location.DistanceSqr(_houndMasterRoomCenter) > 10 * 10, new Action(ctx => Navigator.MoveTo(_houndMasterRoomCenter))),
                //ScriptHelpers.CreateSpreadOutLogic(ctx => true, () => _houndMasterRoomCenter, 6, 10),

                    ScriptHelpers.CreateRunAwayFromBad(ctx => true, () => _houndMasterRoomCenter, 10, 6, u => u is WoWPlayer && ((WoWPlayer)u).HasAura("Piercing Throw") && !u.IsMe),

                    new Decorator<WoWUnit>(boss => StyxWoW.Me.CurrentTarget == boss, ScriptHelpers.CreateTankUnitAtLocation(() => _houndMasterRoomCenter, 10)));
        }

        [EncounterHandler(58632, "Armsmaster Harlan")]
        public Composite ArmsmasterHarlanBehavior()
        {
            var roomCenter = new WoWPoint(1206.015, 443.9851, 0.987926);
            return new PrioritySelector(
                    ScriptHelpers.CreateRunAwayFromBad(ctx => !StyxWoW.Me.IsTank(), 10, u => u.Entry == ArmsmasterHarlan && ((WoWUnit)u).HasAura("Blades of Light")),

                    ScriptHelpers.CreateTankFaceAwayGroupUnit(8),
                // move off stairs.
                    new Decorator(ctx => StyxWoW.Me.Z > 5f,
                        new Helpers.Action<WoWUnit>(boss => Navigator.MoveTo(roomCenter)))
                    );
        }

        [EncounterHandler(59150, "Flameweaver Koegler")]
        public Composite FlameweaverKoeglerBehavior()
        {
            var flamebreathMoveLoc = new WoWPoint(1300.889, 545.713, 12.80321);
            const int dragonsBreath = 113641;
            const uint BookCase = 59155;

            return new PrioritySelector(

                new Decorator<WoWUnit>(boss => boss.CastingSpellId == dragonsBreath && StyxWoW.Me.Location.DistanceSqr(flamebreathMoveLoc) > 3 * 3,
                    new Action(ctx => Navigator.MoveTo(flamebreathMoveLoc))),

                    ScriptHelpers.CreateRunAwayFromBad(ctx => true, () => flamebreathMoveLoc, 10, 15, u => u.Entry == BookCase && ((WoWUnit)u).HasAura("Burning Books"))
                );
        }
    }
}